package com.okq.dao.base.Impl;

import com.okq.dao.base.IBaseDao;
import com.okq.util.page.Page;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BaseDao<T> extends HibernateDaoSupport implements IBaseDao<T> {
    /**
     * 日志
     */
    private static final Logger logger = Logger.getLogger(BaseDao.class);

    @Resource(name = "sessionFactory")
    public void setSF(SessionFactory var1) {
        super.setSessionFactory(var1);
    }

    private SessionFactory sessFac;

    public SessionFactory getSessFac() {
        return sessFac;
    }

    @Autowired
    public void setSessFac(SessionFactory sessFac) {
        this.sessFac = sessFac;
    }

    public Session getSession() {
        return sessFac.getCurrentSession();
    }

    @Override
    public void save(T o) {
        this.getSession().save(o);
    }

    @Override
    public void delete(T o) {
        this.getSession().delete(o);
    }

    @Override
    public void update(T o) {
        this.getSession().update(o);
    }

    @Override
    public void saveOrUpdate(T o) {
        this.getSession().saveOrUpdate(o);
    }

    @Override
    public List<T> find(String hql) {
        return this.getSession().createQuery(hql).list();
    }

    @Override
    public List<T> findMax(String hql, int max) {
        Query query = this.getSession().createQuery(hql);
        query.setMaxResults(max);
        return query.list();
    }

    @Override
    public List<T> findSql(String sql) {
        return this.getSession().createSQLQuery(sql).list();
    }

    @Override
    public List<T> find(String hql, Map<String, Object> param) {
        Query q = this.getSession().createQuery(hql);
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                q.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return q.list();
    }


    @Override
    public List<T> find(String hql, Map<String, Object> param, Integer page, Integer rows) {
        if (page == null || page < 1) {
            page = 1;
        }
        if (rows == null || rows < 1) {
            rows = 10;
        }
        Query q = this.getSession().createQuery(hql);
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                q.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
    }

    @Override
    public T get(Class<T> c, Serializable id) {
        return (T) this.getSession().get(c, id);
    }

    @Override
    public T get(String hql) {
        List<T> l = this.find(hql);
        if (l != null && l.size() > 0) {
            return l.get(0);
        } else {
            return null;
        }
    }

    @Override
    public T get(String hql, Map<String, Object> param) {
        List<T> l = this.find(hql, param);
        if (l != null && l.size() > 0) {
            return l.get(0);
        } else {
            return null;
        }
    }

    @Override
    public Long count(String hql) {
        return (Long) this.getSession().createQuery(hql).uniqueResult();
    }

    @Override
    public Long count(String hql, Map<String, Object> param) {
        Query q = this.getSession().createQuery(hql);
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                q.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return (Long) q.uniqueResult();
    }

    @Override
    public Integer executeHql(String hql) {
        return this.getSession().createQuery(hql).executeUpdate();
    }

    @Override
    public Integer executeHql(String hql, Map<String, Object> param) {
        Query q = this.getSession().createQuery(hql);
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                q.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return q.executeUpdate();
    }

    /**
     * 分页查询
     */
    public Page<T> findByPage(final Page<T> var1, final String var2, final Map<String, Object> var3) {
        try {
            if (logger.isDebugEnabled()) {
                logger.debug("开始查找指定HQL分页数据," + var2);
            }
            return (Page) this.getHibernateTemplate().execute(new HibernateCallback() {
                public Object doInHibernate(Session var1x) throws HibernateException {
                    String var2x = " select count (*) " + BaseDao.this.removeSelect(BaseDao.this.removeOrders(var2));
                    Long var4 = BaseDao.this.count(var2x, var3);
                    Query var5 = BaseDao.this.createQuery(var1x, var2, var3);
                    if (var1.isFirstSetted()) {
                        var5.setFirstResult(var1.getFirst());
                    }
                    if (var1.isPageSizeSetted()) {
                        var5.setMaxResults(var1.getPageSize());
                    }
                    var1.setTotalCount(var4.intValue());
                    var1.setResult(var5.list());
                    if (BaseDao.logger.isDebugEnabled()) {
                        BaseDao.logger.debug("查找指定HQL分页数据成功," + var2);
                    }
                    return var1;
                }
            });
        } catch (RuntimeException var5) {
            logger.error("分页查询异常，HQL：" + var2, var5);
            throw var5;
        }
    }

    private String removeSelect(String var1) {
        int var2 = var1.toLowerCase().indexOf("from");
        return var1.substring(var2);
    }

    private String removeOrders(String var1) {
        Pattern var2 = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", 2);
        Matcher var3 = var2.matcher(var1);
        StringBuffer var4 = new StringBuffer();
        while (var3.find()) {
            var3.appendReplacement(var4, "");
        }

        var3.appendTail(var4);
        return var4.toString();
    }

    private Query createQuery(Session var1, String var2, Map<String, Object> var3) {
        Query var4 = var1.createQuery(var2);
        if (var3 != null && !var3.isEmpty()) {
            for (Map.Entry<String, Object> entry : var3.entrySet()) {
                var4.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return var4;
    }

}
